home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Source Code
/
C
/
Games
/
SpriteFight 2002 v2.0a1
/
StefSpriteStuff.c
< prev
next >
Wrap
Text File
|
1996-05-01
|
17KB
|
567 lines
// StefSpriteStuff.c by Stefan Sinclair ©1995-1996 All Rights Reserved
#include "Spritez.h"
#include "SpriteCicnNumbers.h"
#include "SpriteError.h"
#include "SpriteSecretCodes.h"
#define kErrorAlertID 150
#define kEmptyString "\p"
extern SpriteGameRec spriteGame;
extern SndChannelPtr gSoundChanP1, gSoundChanP2, gSoundChanGame;
extern Handle gP1SoundH[kNumSpriteSounds], gP2SoundH[kNumSpriteSounds];
extern RgnHandle gWorkRgn; // defined in Spritez.c
extern PixPatHandle gLifePixPatH;
extern Point player1TopLeft, projectile1TopLeft;
extern Point player2TopLeft, projectile2TopLeft;
extern CWindowPtr gWindowP;
extern Boolean gQT, gSoundOff, gSoundMax, gSoundMegaMax;
extern short gSpriteHeight, gSpriteWidth;
extern Rect gPlayer1DamageRect, gPlayer2DamageRect;
extern Boolean gSecretCode[kNumSecretCodes];
/** CombatMoveProc **/
// Here, reset sprite frame range as necessary depending on current & previous actions.
SW_FUNC void CombatMoveProc(SpritePtr srcSpriteP, Point* spritePoint)
{
unsigned char *spriteDataPtr; // use as an array of 8 u. chars.
Boolean bSpriteAlive;
// Access sprite's userData
spriteDataPtr = (unsigned char *)&srcSpriteP->userData;
// Assign the spritePoint to the correct sprite
switch(spriteDataPtr[kSpriteIDNum])
{
case kPlayer1Sprite:
case kComputer1Sprite:
player1TopLeft = *spritePoint;
break;
case kPlayer2Sprite:
case kComputer2Sprite:
player2TopLeft = *spritePoint;
break;
default:
DoError(kUnknownSpriteInGame, TRUE);
break;
}
// Is the sprite still alive after this round of events?
bSpriteAlive = PlayerStatusCheck(srcSpriteP, spritePoint);
if(spriteDataPtr[kSpriteIDNum] == kPlayer1Sprite ||
spriteDataPtr[kSpriteIDNum] == kComputer1Sprite)
{
gPlayer1DamageRect.left = kP1LifeRectLeft + spriteDataPtr[kSpriteLife] - kSpriteMinLife;
FillCRect(&gPlayer1DamageRect, gLifePixPatH);
}
else
{
gPlayer2DamageRect.left = kP2LifeRectLeft + spriteDataPtr[kSpriteLife] - kSpriteMinLife;
FillCRect(&gPlayer2DamageRect, gLifePixPatH);
}
// hit bottom - CHECKED IN GRAVITY CHECK
// hit left wall
if (srcSpriteP->destFrameRect.left <= srcSpriteP->moveBoundsRect.left)
{
srcSpriteP->horizMoveDelta = kMaxSpeed/2;
spritePoint->h = srcSpriteP->moveBoundsRect.left + 1;
}
// hit right wall
if (srcSpriteP->destFrameRect.right >= srcSpriteP->moveBoundsRect.right)
{
srcSpriteP->horizMoveDelta = -kMaxSpeed/2;
spritePoint->h = srcSpriteP->moveBoundsRect.right - gSpriteWidth - 1;
}
}
/** ProjectileMoveProc **/
// Here, reset sprite frame range as necessary depending on current & previous actions.
SW_FUNC void ProjectileMoveProc(SpritePtr srcSpriteP, Point* spritePoint)
{
unsigned char *spriteDataPtr; // use as an array of 8 u. chars.
Boolean visible;
// Access sprite's userData
spriteDataPtr = (unsigned char *)&srcSpriteP->userData;
visible = ProjectileStatusCheck(srcSpriteP, spritePoint);
if(!visible)
{
srcSpriteP->horizMoveDelta = 0;
srcSpriteP->vertMoveDelta = 0;
SWSetSpriteVisible(srcSpriteP, FALSE);
}
// hit left wall
else if (srcSpriteP->destFrameRect.left <= srcSpriteP->moveBoundsRect.left)
{
srcSpriteP->horizMoveDelta = 0;
srcSpriteP->vertMoveDelta = 0;
spriteDataPtr[kCurrentAction] = aProjectileIdle;
SWSetSpriteVisible(srcSpriteP, FALSE);
}
// hit right wall
else if (srcSpriteP->destFrameRect.right >= srcSpriteP->moveBoundsRect.right)
{
srcSpriteP->horizMoveDelta = 0;
srcSpriteP->vertMoveDelta = 0;
spriteDataPtr[kCurrentAction] = aProjectileIdle;
SWSetSpriteVisible(srcSpriteP, FALSE);
}
// hit bottomwall
else if (srcSpriteP->destFrameRect.bottom > srcSpriteP->moveBoundsRect.bottom)
{
srcSpriteP->horizMoveDelta = 0;
srcSpriteP->vertMoveDelta = 0;
spriteDataPtr[kCurrentAction] = aProjectileIdle;
SWSetSpriteVisible(srcSpriteP, FALSE);
}
// hit top wall
else if (srcSpriteP->destFrameRect.top <= srcSpriteP->moveBoundsRect.top)
{
srcSpriteP->horizMoveDelta = 0;
srcSpriteP->vertMoveDelta = 0;
spriteDataPtr[kCurrentAction] = aProjectileIdle;
SWSetSpriteVisible(srcSpriteP, FALSE);
}
}
// CombatSpriteCollideProc----------------------------------------------------------------
void CombatSpriteCollideProc(SpritePtr srcSpriteP,SpritePtr dstSpriteP,Rect* sectRect)
{
register short tempDelta;
Rect rgnRect;
unsigned char *srcSpriteDataPtr,*dstSpriteDataPtr; // use as an array of 8 u. chars.
short srcDrxn, dstDrxn, damage = 0;
Boolean dstSpriteHit = FALSE, srcSpriteHit = FALSE, somebodyHit;
static Boolean flipFlop; // to counter the player 1/2 advantage
// Access sprite's userData
srcSpriteDataPtr = (unsigned char *)&srcSpriteP->userData;
dstSpriteDataPtr = (unsigned char *)&dstSpriteP->userData;
// If both sprites use the same collision routine (this one),ignore the second collision.
if ((!srcSpriteP->isVisible || !dstSpriteP->isVisible) ||
((srcSpriteP->spriteCollideProc == dstSpriteP->spriteCollideProc) &&
(srcSpriteP > dstSpriteP)))
return;
rgnRect = (**srcSpriteP->curFrameP->maskRgn).rgnBBox;
// move the mask region to the new sprite location
OffsetRgn(srcSpriteP->curFrameP->maskRgn,
(srcSpriteP->destFrameRect.left - rgnRect.left) +
srcSpriteP->curFrameP->offsetPoint.h,
(srcSpriteP->destFrameRect.top - rgnRect.top) +
srcSpriteP->curFrameP->offsetPoint.v);
rgnRect = (**dstSpriteP->curFrameP->maskRgn).rgnBBox;
// move the mask region to the new sprite location
OffsetRgn(dstSpriteP->curFrameP->maskRgn,
(dstSpriteP->destFrameRect.left - rgnRect.left) +
dstSpriteP->curFrameP->offsetPoint.h,
(dstSpriteP->destFrameRect.top - rgnRect.top) +
dstSpriteP->curFrameP->offsetPoint.v);
SectRgn(srcSpriteP->curFrameP->maskRgn, dstSpriteP->curFrameP->maskRgn, gWorkRgn);
if (!EmptyRgn(gWorkRgn)) // There is an overlap
{
Point sPt;
Boolean srcSide;
// A sprite's projectile cannot damage him or herself
// Player 1
if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer1Sprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite))
return;
if((srcSpriteDataPtr[kSpriteIDNum] == kComputer1Sprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite))
return;
if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kPlayer1Sprite))
return;
if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer1ProjectileSprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kComputer1Sprite))
return;
// Player 2
if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer2Sprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite))
return;
if((srcSpriteDataPtr[kSpriteIDNum] == kComputer2Sprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite))
return;
if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kPlayer2Sprite))
return;
if((srcSpriteDataPtr[kSpriteIDNum] == kPlayer2ProjectileSprite) &&
(dstSpriteDataPtr[kSpriteIDNum] == kComputer1Sprite))
return;
// Where am I?
switch(srcSpriteDataPtr[kSpriteIDNum])
{
case kPlayer1Sprite:
case kComputer1Sprite:
sPt = player1TopLeft;
break;
case kPlayer2Sprite:
case kComputer2Sprite:
sPt = player2TopLeft;
break;
case kPlayer1ProjectileSprite:
sPt = projectile1TopLeft;
break;
case kPlayer2ProjectileSprite:
sPt = projectile2TopLeft;
break;
}
// Which drxn to go if hit?
srcSide = GetSpriteSide(srcSpriteDataPtr);
if(srcSide == kLeftSide)
{
srcDrxn = -2; // I go left
dstDrxn = 2; // You go right
}
else
{
srcDrxn = 2; // I go right
dstDrxn = -2; // You go left
}
somebodyHit = ((srcSpriteDataPtr[kCurrentAction] == aKick ||
srcSpriteDataPtr[kCurrentAction] == aPunch ||
srcSpriteDataPtr[kCurrentAction] == aUppercut ||
srcSpriteDataPtr[kCurrentAction] == aJumpAttack ||
srcSpriteDataPtr[kCurrentAction] == aJumpPunch ||
srcSpriteDataPtr[kCurrentAction] == aJumpKick ||
srcSpriteDataPtr[kCurrentAction] == aProjectileShoot) ? TRUE : FALSE);
if(somebodyHit)
{
switch(srcSpriteDataPtr[kSpriteIDNum])
{
case kPlayer1Sprite:
case kComputer1Sprite:
PlaySound(gP1SoundH[sGotHit], gSoundChanP1);
break;
case kPlayer2Sprite:
case kComputer2Sprite:
PlaySound(gP2SoundH[sGotHit], gSoundChanP2);
break;
}
switch(srcSpriteDataPtr[kCurrentAction])
{
case aKick:
case aPunch:
case aJumpAttack:
case aJumpKick:
case aJumpPunch:
case aProjectileShoot:
// swap h/v delta's
dstSpriteP->horizMoveDelta = kWhipLashVelocity*dstDrxn;
if(dstSpriteDataPtr[kCurrentAction] != aBlock)
{
dstSpriteHit = TRUE;
}
break;
case aUppercut:
// swap h/v delta's
dstSpriteP->horizMoveDelta = kWhipLashVelocity*dstDrxn;
if(dstSpriteDataPtr[kCurrentAction] != aBlock)
{
dstSpriteP->vertMoveDelta = -10*kWhipLashVelocity;
dstSpriteHit = TRUE;
}
break;
}
}
somebodyHit = ((dstSpriteDataPtr[kCurrentAction] == aKick ||
dstSpriteDataPtr[kCurrentAction] == aPunch ||
dstSpriteDataPtr[kCurrentAction] == aUppercut ||
dstSpriteDataPtr[kCurrentAction] == aJumpAttack ||
dstSpriteDataPtr[kCurrentAction] == aJumpPunch ||
dstSpriteDataPtr[kCurrentAction] == aJumpKick ||
dstSpriteDataPtr[kCurrentAction] == aProjectileShoot) ? TRUE : FALSE);
if(somebodyHit)
{
switch(srcSpriteDataPtr[kSpriteIDNum])
{
case kPlayer1Sprite:
case kComputer1Sprite:
PlaySound(gP1SoundH[sGotHit], gSoundChanP1);
break;
case kPlayer2Sprite:
case kComputer2Sprite:
PlaySound(gP2SoundH[sGotHit], gSoundChanP2);
break;
}
switch(dstSpriteDataPtr[kCurrentAction])
{
case aKick:
case aPunch:
case aJumpAttack:
case aJumpKick:
case aJumpPunch:
case aProjectileShoot:
// swap h/v delta's
srcSpriteP->horizMoveDelta = kWhipLashVelocity*srcDrxn;
if(srcSpriteDataPtr[kCurrentAction] != aBlock)
{
srcSpriteHit = TRUE;
}
break;
case aUppercut:
// swap h/v delta's
srcSpriteP->horizMoveDelta = kWhipLashVelocity*srcDrxn;
if(srcSpriteDataPtr[kCurrentAction] != aBlock)
{
srcSpriteP->vertMoveDelta = -10*kWhipLashVelocity;
srcSpriteHit = TRUE;
}
break;
}
}
// Was anybody hurt?
// Only 1 hit per attack move!!!
if(flipFlop) // to counter the player 1/2 advantage
{
flipFlop = FALSE;
//goto FLIP_FLOP; // I did have this uncommented
}
else
{
flipFlop = TRUE;
}
if(srcSpriteHit && srcSpriteDataPtr[kCurrentAction] != aGotHit
&& dstSpriteDataPtr[kCurrentAction] != aDying)
{
srcSpriteDataPtr[kCurrentAction] = aGotHit;
switch(dstSpriteDataPtr[kCurrentAction])
{
case aPunch:
damage = kPunchDamage;
dstSpriteDataPtr[kCurrentAction] = aPostAttack;
break;
case aKick:
damage = kKickDamage;
dstSpriteDataPtr[kCurrentAction] = aPostAttack;
break;
case aUppercut:
damage = kUppercutDamage;
dstSpriteDataPtr[kCurrentAction] = aPostAttack;
break;
case aProjectileShoot:
damage = kProjectileDamage;
dstSpriteDataPtr[kCurrentAction] = aProjectileIdle;
break;
case aJumpAttack:
damage = kJumpAttackDamage;
dstSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
break;
case aJumpPunch:
damage = kJumpPunchDamage;
dstSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
break;
case aJumpKick:
damage = kJumpKickDamage;
dstSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
break;
default:
break;
}
srcSpriteDataPtr[kSpriteLife] -= damage;
// Double damage code?
if(gSecretCode[kDoubleDamageCode])
srcSpriteDataPtr[kSpriteLife] -= damage;
}
FLIP_FLOP:
// reset damage to zero
damage = 0;
if(dstSpriteHit && dstSpriteDataPtr[kCurrentAction] != aGotHit
&& dstSpriteDataPtr[kCurrentAction] != aDying)
{
dstSpriteDataPtr[kCurrentAction] = aGotHit;
switch(srcSpriteDataPtr[kCurrentAction])
{
case aPunch:
damage = kPunchDamage;
// Double damage code?
if(gSecretCode[kDoubleDamageCode])
dstSpriteDataPtr[kSpriteLife] -= kPunchDamage;
srcSpriteDataPtr[kCurrentAction] = aPostAttack;
break;
case aKick:
damage = kKickDamage;
srcSpriteDataPtr[kCurrentAction] = aPostAttack;
break;
case aUppercut:
damage = kUppercutDamage;
srcSpriteDataPtr[kCurrentAction] = aPostAttack;
break;
case aProjectileShoot:
damage = kProjectileDamage;
srcSpriteDataPtr[kCurrentAction] = aProjectileIdle;
break;
case aJumpAttack:
damage = kJumpAttackDamage;
srcSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
break;
case aJumpPunch:
damage = kJumpPunchDamage;
srcSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
break;
case aJumpKick:
damage = kJumpKickDamage;
srcSpriteDataPtr[kCurrentAction] = aPostJumpAttack;
break;
default:
break;
}
dstSpriteDataPtr[kSpriteLife] -= damage;
// Double damage code?
if(gSecretCode[kDoubleDamageCode])
dstSpriteDataPtr[kSpriteLife] -= damage;
}
}
}
/********** PlaySound ***************/
/* March 1995 */
void PlaySound(Handle soundHandle, SndChannelPtr sndChan)
{
OSErr err;
SndCommand command;
SCStatus theStatus;
long offset;
if(gSoundOff == TRUE) // accessed via secret menu
return;
if(soundHandle == NULL)
DoError(kNULLSoundHandle, TRUE);
//HLock(soundHandle); - I lock them ahead of time.
if(sndChan == NULL)
DoError(kNULLSoundChannel,TRUE);
if(SndChannelBusy(sndChan))
{
command.cmd = flushCmd;
command.param1 = command.param2 = 0;
err = SndDoImmediate( sndChan, &command);
if(err)
DoError(kCouldNotFlushSoundChannel, TRUE);
command.cmd = quietCmd;
command.param1 = command.param2 = 0;
err = SndDoImmediate( sndChan, &command);
if(err)
DoError(kCouldNotQuietSoundChannel, TRUE);
}
if(gSoundMax == TRUE) // accessed via a hidden menu
{
command.cmd = volumeCmd;
command.param1 = 0; // unused
command.param2 = 0x03000300; // 3X Full volume! whoa!
err = SndDoImmediate(sndChan, &command);
if(err != noErr)
DoError(kNeedSoundMgr3ForMegaVolume, TRUE);
}
if(gSoundMegaMax == TRUE) // accessed via a hidden menu
{
command.cmd = volumeCmd;
command.param1 = 0; // unused
command.param2 = 0x07000700; // 7X Full volume! ZOINKS!!!
err = SndDoImmediate(sndChan, &command);
if(err != noErr)
DoError(kNeedSoundMgr3ForMegaVolume, TRUE);
}
err = GetSoundHeaderOffset( (SndListHandle)soundHandle,&offset);
if(err != noErr)
DoError(kCouldNotGetSoundHeaderOffset, TRUE);
command.cmd = bufferCmd;
command.param1 = 0;
command.param2 = (long)(*soundHandle + offset);
err = SndDoImmediate( sndChan,&command);
if( err != noErr)
DoError(kSoundBufferError, TRUE);
}
/********** PlaySound ***************/
/* April 1996 */
void LoopSound(Handle soundHandle, SndChannelPtr sndChan)
{
OSErr err;
SndCommand command;
SCStatus theStatus;
long offset;
if(gSoundOff == TRUE) // accessed via secret menu
return;
if(soundHandle == NULL)
DoError(kNULLSoundHandle, TRUE);
//HLock(soundHandle); - I lock them ahead of time.
if(sndChan == NULL)
DoError(kNULLSoundChannel,TRUE);
if(SndChannelBusy(sndChan))
{
return; // it's busy playing already!
}
err = GetSoundHeaderOffset( (SndListHandle)soundHandle,&offset);
if(err != noErr)
DoError(kCouldNotGetSoundHeaderOffset, TRUE);
command.cmd = bufferCmd;
command.param1 = 0;
command.param2 = (long)(*soundHandle + offset);
err = SndDoImmediate( sndChan,&command);
if( err != noErr)
DoError(kSoundBufferError, TRUE);
}
/********** PlaySound ***************/
/* March 1995 */
void StopPlayingSound(SndChannelPtr sndChan)
{
OSErr err;
SndCommand command;
if(sndChan == NULL)
DoError(kNULLSoundChannel,TRUE);
if(SndChannelBusy(sndChan))
{
command.cmd = flushCmd;
command.param1 = command.param2 = 0;
err = SndDoImmediate( sndChan, &command);
if(err)
DoError(kCouldNotFlushSoundChannel, TRUE);
command.cmd = quietCmd;
command.param1 = command.param2 = 0;
err = SndDoImmediate( sndChan, &command);
if(err)
DoError(kCouldNotQuietSoundChannel, TRUE);
}
}
/* CODE EXAMPLE #1 */
short isPressed(unsigned short k)
// k = any keyboard scan code, 0-127
{
unsigned char km[16];
StefGetKeys;
return ( ( km[k>>3] >> (k & 7) ) & 1);
}
void StartWaiting(void)
{
Cursor watchCurs;
CursHandle watchCursH;
watchCursH = GetCursor(watchCursor);
watchCurs = **watchCursH;
SetCursor(&watchCurs);
DisposeHandle((Handle)watchCursH);
}
void StopWaiting(void)
{
SetCursor(&qd.arrow);
}